home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / route.c < prev    next >
C/C++ Source or Header  |  1994-10-22  |  8KB  |  350 lines

  1. /*
  2.  *          PPP Routing related Module
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1994, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan, Inc.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  */
  21. #include <sys/types.h>
  22. #include <machine/endian.h>
  23. #include <sys/param.h>
  24. #include <sys/socket.h>
  25. #include <net/route.h>
  26. #include <sys/ioctl.h>
  27. #include <net/if.h>
  28. #include <errno.h>
  29. #include <netinet/in_systm.h>
  30. #include <netinet/in.h>
  31. #include <arpa/inet.h>
  32. #include <sys/kinfo.h>
  33. #include <stdlib.h>
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37.  
  38. static int IfIndex;
  39.  
  40. struct rtmsg {
  41.   struct rt_msghdr m_rtm;
  42.   char m_space[64];
  43. };
  44.  
  45. static int seqno;
  46.  
  47. void
  48. OsSetRoute(cmd, dst, gateway, mask)
  49. int cmd;
  50. struct in_addr dst;
  51. struct in_addr gateway;
  52. struct in_addr mask;
  53. {
  54.   struct rtmsg rtmes;
  55.   int s, nb, wb;
  56.   char *cp;
  57.   u_long *lp;
  58.   struct sockaddr_in rtdata;
  59.  
  60.   s = socket(PF_ROUTE, SOCK_RAW, 0);
  61.   if (s < 0)
  62.     logprintf("socket\n");
  63.  
  64.   bzero(&rtmes, sizeof(rtmes));
  65.   rtmes.m_rtm.rtm_version = RTM_VERSION;
  66.   rtmes.m_rtm.rtm_type = cmd;
  67.   rtmes.m_rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
  68.   if (cmd == RTM_ADD) rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
  69.   rtmes.m_rtm.rtm_seq = ++seqno;
  70.   rtmes.m_rtm.rtm_pid = getpid();
  71.   rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
  72.  
  73.   bzero(&rtdata, sizeof(rtdata));
  74.   rtdata.sin_len = 16;
  75.   rtdata.sin_family = AF_INET;
  76.   rtdata.sin_port = 0;
  77.   rtdata.sin_addr = dst;
  78.  
  79.   cp = rtmes.m_space;
  80.   bcopy(&rtdata, cp, 16);
  81.   cp += 16;
  82.   if (gateway.s_addr) {
  83.     rtdata.sin_addr = gateway;
  84.     bcopy(&rtdata, cp, 16);
  85.     cp += 16;
  86.   }
  87.  
  88.   if (dst.s_addr == INADDR_ANY)
  89.     mask.s_addr = INADDR_ANY;
  90.  
  91.   lp = (u_long *)cp;
  92.  
  93.   if (mask.s_addr) {
  94.     *lp++ = 8;
  95.     cp += sizeof(int);
  96.     *lp = mask.s_addr;
  97.   } else
  98.     *lp = 0;
  99.   cp += sizeof(u_long);
  100.  
  101.   nb = cp - (char *)&rtmes;
  102.   rtmes.m_rtm.rtm_msglen = nb;
  103.   wb = write(s, &rtmes, nb);
  104.   if (wb < 0) {
  105.     perror("write");
  106.   }
  107. #ifdef DEBUG
  108.   logprintf("wrote %d: dst = %x, gateway = %x\n", nb, dst.s_addr, gateway.s_addr);
  109. #endif
  110.   close(s);
  111. }
  112.  
  113. static void
  114. p_sockaddr(sa, width)
  115. struct sockaddr *sa;
  116. int width;
  117. {
  118.   register char *cp;
  119.   register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
  120.  
  121.   cp = (sin->sin_addr.s_addr == 0) ? "default" :
  122.        inet_ntoa(sin->sin_addr);
  123.   printf("%-*.*s ", width, width, cp);
  124. }
  125.  
  126. struct bits {
  127.   short b_mask;
  128.   char  b_val;
  129. } bits[] = {
  130.   { RTF_UP,      'U' },
  131.   { RTF_GATEWAY,  'G' },
  132.   { RTF_HOST,      'H' },
  133.   { RTF_DYNAMIC,  'D' },
  134.   { RTF_MODIFIED, 'M' },
  135.   { RTF_CLONING,  'C' },
  136.   { RTF_XRESOLVE, 'X' },
  137.   { RTF_LLINFO,   'L' },
  138.   { RTF_REJECT,   'R' },
  139.   { 0 }
  140. };
  141.  
  142. static void
  143. p_flags(f, format)
  144. register int f;
  145. char *format;
  146. {
  147.   char name[33], *flags;
  148.   register struct bits *p = bits;
  149.  
  150.   for (flags = name; p->b_mask; p++)
  151.     if (p->b_mask & f)
  152.       *flags++ = p->b_val;
  153.   *flags = '\0';
  154.   printf(format, name);
  155. }
  156.  
  157. int
  158. ShowRoute()
  159. {
  160.   struct rt_msghdr *rtm;
  161.   struct sockaddr *sa;
  162.   char *sp, *ep, *cp;
  163.   u_char *wp;
  164.   int *lp;
  165.   int needed, nb;
  166.   u_long mask;
  167.  
  168.   needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0);
  169.   if (needed < 0)
  170.     return(1);
  171.   sp = malloc(needed);
  172.   if (sp == NULL)
  173.     return(1);
  174.   if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0)
  175.     return(1);
  176.   ep = sp + needed;
  177.  
  178.   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
  179.     rtm = (struct rt_msghdr *)cp;
  180.     sa = (struct sockaddr *)(rtm + 1);
  181.     mask = 0xffffffff;
  182.     if (rtm->rtm_addrs == RTA_DST)
  183.       p_sockaddr(sa, 36);
  184.     else {
  185.       wp = (u_char *)cp + rtm->rtm_msglen;
  186.       p_sockaddr(sa, 16);
  187.       if (sa->sa_len == 0)
  188.     sa->sa_len = sizeof(long);
  189.       sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
  190.       p_sockaddr(sa, 18);
  191.       lp = (int *)(sa->sa_len + (char *)sa);
  192.       if ((char *)lp < (char *)wp && *lp) {
  193. #ifdef DEBUG
  194.     logprintf(" flag = %x, rest = %d", rtm->rtm_flags, *lp);
  195. #endif
  196.     wp = (u_char *)(lp + 1);
  197.     mask = 0;
  198.     for (nb = *lp; nb > 4; nb--) {
  199.       mask <<= 8;
  200.       mask |= *wp++;
  201.     }
  202.     for (nb = 8 - *lp; nb > 0; nb--)
  203.       mask <<= 8;
  204.       }
  205.     }
  206.     printf("%08x  ", mask);
  207.     p_flags(rtm->rtm_flags & (RTF_UP|RTF_GATEWAY|RTF_HOST), "%-6.6s ");
  208.     printf("(%d)\n", rtm->rtm_index);
  209.   }
  210.  
  211.   return(1);
  212. }
  213.  
  214. /*
  215.  *  Delete routes associated with our interface
  216.  */
  217. void
  218. DeleteIfRoutes(all)
  219. int all;
  220. {
  221.   struct rt_msghdr *rtm;
  222.   struct sockaddr *sa;
  223.   struct in_addr dstnet, gateway;
  224.   int needed;
  225.   char *sp, *cp, *ep;
  226.   u_long mask;
  227.   int *lp, nb;
  228.   u_char *wp;
  229.  
  230. #ifdef DEBUG
  231.   logprintf("DeleteIfRoutes (%d)\n", IfIndex);
  232. #endif
  233.   needed = getkerninfo(KINFO_RT_DUMP, 0, 0, 0);
  234.  
  235.   if (needed < 0)
  236.     return;
  237.  
  238.   sp = malloc(needed);
  239.   if (sp == NULL)
  240.     return;
  241.  
  242.   if (getkerninfo(KINFO_RT_DUMP, sp, &needed, 0) < 0) {
  243.     free(sp);
  244.     return;
  245.   }
  246.   ep = sp + needed;
  247.  
  248.   for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
  249.     rtm = (struct rt_msghdr *)cp;
  250.     sa = (struct sockaddr *)(rtm + 1);
  251. #ifdef DEBUG
  252.     logprintf("addrs: %x, index: %d, flags: %x, dstnet: %x\n",
  253.     rtm->rtm_addrs, rtm->rtm_index, rtm->rtm_flags,
  254.     ((struct sockaddr_in *)sa)->sin_addr);
  255. #endif
  256.     if (rtm->rtm_addrs != RTA_DST &&
  257.        (rtm->rtm_index == IfIndex) &&
  258.        (all || (rtm->rtm_flags & RTF_GATEWAY))) {
  259.       dstnet = ((struct sockaddr_in *)sa)->sin_addr;
  260.       wp = (u_char *)cp + rtm->rtm_msglen;
  261.       if (sa->sa_len == 0)
  262.     sa->sa_len = sizeof(long);
  263.       sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
  264.       gateway = ((struct sockaddr_in *)sa)->sin_addr;
  265.       lp = (int *)(sa->sa_len + (char *)sa);
  266.       mask = 0;
  267.       if ((char *)lp < (char *)wp && *lp) {
  268. #ifdef DEBUG
  269.     printf(" flag = %x, rest = %d", rtm->rtm_flags, *lp);
  270. #endif
  271.     wp = (u_char *)(lp + 1);
  272.     for (nb = *lp; nb > 4; nb--) {
  273.       mask <<= 8;
  274.       mask |= *wp++;
  275.     }
  276.     for (nb = 8 - *lp; nb > 0; nb--)
  277.       mask <<= 8;
  278.       }
  279. #ifdef DEBUG
  280.       logprintf("## %s ", inet_ntoa(dstnet));
  281.       logprintf(" %s  %d\n", inet_ntoa(gateway), rtm->rtm_index);
  282. #endif
  283.       if (dstnet.s_addr == INADDR_ANY) {
  284.         gateway.s_addr = INADDR_ANY;
  285.         mask = INADDR_ANY;
  286.       }
  287.       OsSetRoute(RTM_DELETE, dstnet, gateway, htonl(mask));
  288.     }
  289. #ifdef DEBUG
  290.     else if (rtm->rtm_index == IfIndex) {
  291.       logprintf("??? addrs: %x, flags = %x\n", rtm->rtm_addrs, rtm->rtm_flags);
  292.     }
  293. #endif
  294.   }
  295.   free(sp);
  296. }
  297.  
  298. int
  299. GetIfIndex(name)
  300. char *name;
  301. {
  302.   struct ifreq *ifrp;
  303.   int s, len, elen, index;
  304.   struct ifconf ifconfs;
  305.   struct ifreq reqbuf[32];
  306.  
  307.   s = socket(AF_INET, SOCK_DGRAM, 0);
  308.   if (s < 0) {
  309.     perror("socket");
  310.     return(-1);
  311.   }
  312.  
  313.   ifconfs.ifc_len = sizeof(reqbuf);
  314.   ifconfs.ifc_buf = (caddr_t)reqbuf;
  315.   if (ioctl(s, SIOCGIFCONF, &ifconfs) < 0) {
  316.     perror("IFCONF");
  317.     return(-1);
  318.   }
  319.  
  320.   ifrp = ifconfs.ifc_req;
  321.  
  322.   index = 1;
  323.   for (len = ifconfs.ifc_len; len > 0; len -= sizeof(struct ifreq)) {
  324.     elen = ifrp->ifr_addr.sa_len - sizeof(struct sockaddr);
  325.     if (ifrp->ifr_addr.sa_family == AF_LINK) {
  326. #ifdef DEBUG
  327.       logprintf("%d: %-*.*s, %d, %d\n", index, IFNAMSIZ, IFNAMSIZ, ifrp->ifr_name,
  328.        ifrp->ifr_addr.sa_family, elen);
  329. #endif
  330.       if (strcmp(ifrp->ifr_name, name) == 0) {
  331.         IfIndex = index;
  332.         return(index);
  333.       }
  334. #if defined(__FreeBSD__) || (_BSDI_VERSION >= 199312)
  335.       index++;
  336. #endif
  337.     }
  338.  
  339.     len -= elen;
  340.     ifrp = (struct ifreq *)((char *)ifrp + elen);
  341.     ifrp++;
  342. #if defined(_BSDI_VERSION) && (_BSDI_VERSION < 199312)
  343.     index++;
  344. #endif
  345.   }
  346.  
  347.   close(s);
  348.   return(-1);
  349. }
  350.